﻿//_______________________________________________________________________________________________________________________
// Copy Right (c) 2010, 2011 SapiensIT Consulting GmbH, all rights reserved
//_______________________________________________________________________________________________________________________
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT
// NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
//_______________________________________________________________________________________________________________________
// PROJECT:     sapiens.at.SharePoint.LookupPicker (SharePoint 2010/V4)
//_______________________________________________________________________________________________________________________
// VERSION:     2.0
//_______________________________________________________________________________________________________________________
// DESCRIPTION: 
//_______________________________________________________________________________________________________________________
// LICENSE:     Different licens Types apply to different file types:
//               - Source code files are governed by the MICROSOFT PUBLIC LICENSE (Ms-PL)
//               - Binary files are governed by MSDN CODE GALLERY BINARY LICENSE
//               - Documentation files are governed by CREATIVE COMMONS ATTRIBUTION 3.0 LICENSE
//
//               The licenses can be found at the projects source location.
//               If you do not agree, don't use it!
// 
//_______________________________________________________________________________________________________________________
// Start SharePoint Branding, visit http://www.cliggin.com! Visit us on http://www.sapiens.at! Tell your friends! 
//_______________________________________________________________________________________________________________________
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.SharePoint.WebControls;
using Microsoft.SharePoint;
using Sapiens.at.SharePoint.Utils;
using QB = Sapiens.at.SharePoint.Utils.QueryBuilder;

namespace Sapiens.at.SharePoint.Fields
{
    /// <summary>
    /// The LookupPicker control showing a textbox with buttons to validate content and to open a search dialog.
    /// </summary>
    public class LookupPicker : EntityEditorWithPicker
    {
        private SPListItemCollection _currentMatches;

        LookupPickerData _pickerData;
        /// <summary>
        /// Gets or sets the properties of the lookup picker field.
        /// </summary>
        public LookupPickerData PickerData
        {
            get
            {
                if (_pickerData == null)
                {
                    _pickerData = LookupPickerData.Deserialize(CustomProperty);
                }
                return _pickerData;
            }
            set
            {
                if (value != null)
                {
                    _pickerData = value;
                    CustomProperty = LookupPickerData.Serialize(value);
                }
                else
                {
                    CustomProperty = null;
                    _pickerData = null;
                }
            }
        }
        SPWeb _web;
        SPWeb Web
        {
            get
            {
                if (_web == null) { _web = SPContext.Current.Site.OpenWeb(PickerData.WebID); }
                return _web;
            }
        }
        SPList _list;
        SPList List
        {
            get
            {
                if (_list == null) { _list = Web.Lists[PickerData.ListID]; }
                return _list;
            }
        }


        /// <summary>
        /// Initializes the control.
        /// </summary>
        /// <param name="e"></param>
        protected override void OnInit(EventArgs e)
        {
            base.OnInit(e);
            PickerDialogType = typeof(LookupPickerDialog);
            ValidatorEnabled = true;
            AllowTypeIn = true;
            MultiSelect = PickerData.AllowMultiValue;
        }

        /// <summary>
        /// Validates the searchresult.
        /// </summary>
        /// <param name="needsValidation"></param>
        /// <returns></returns>
        public override PickerEntity ValidateEntity(PickerEntity needsValidation)
        {
            if (needsValidation.IsResolved) { return needsValidation; }

            var displayText = needsValidation.DisplayText = needsValidation.DisplayText.Replace("string;#", "");
            _currentMatches = SearchListItems(displayText);

            switch (_currentMatches.Count)
            {
                case 0:
                    needsValidation.Description = "No match";
                    break;
                case 1:
                    needsValidation = GetEntity(_currentMatches[0]);
                    break;
                default:
                    needsValidation.Description = "Multiple matches";
                    break;
            }
            return needsValidation;
        }

        /// <summary>
        /// Creates entities from the found listitems.
        /// </summary>
        /// <param name="unresolvedText"></param>
        /// <returns></returns>
        protected override PickerEntity[] ResolveErrorBySearch(string unresolvedText)
        {
            if (_currentMatches == null || _currentMatches.Count == 0) { return null; }
            
            List<PickerEntity> resolvedItems = null;

            if (!String.IsNullOrEmpty(unresolvedText) && _currentMatches.Count > 0)
            {
                resolvedItems = new List<PickerEntity>();
                foreach (SPListItem listItem in _currentMatches)
                {
                    resolvedItems.Add(GetEntity(listItem));
                }
            }
            return resolvedItems != null ? resolvedItems.ToArray() : null;
        }

        /// <summary>
        /// Disposes the control.
        /// </summary>
        public override void Dispose()
        {
            if (_web != null)
            {
                _web.Dispose();
            }
            base.Dispose();
        }

        /// <summary>
        /// Returns the PickerEntity for a listitem.
        /// </summary>
        /// <param name="id">The id of the listitem</param>
        /// <returns></returns>
        public PickerEntity GetEntity(int id)
        {
            if (id == 0) { return null; }
            try
            {
                var item = List.GetItemById(id);
                return item != null ? GetEntity(item) : null;
            }
            catch
            {
                return null;
            }
        }

        private PickerEntity GetEntity(SPListItem item)
        {
            var displayText = item[PickerData.LookupField].ToString().Replace("string;#", "");
            PickerEntity entity = new PickerEntity()
            {
                DisplayText = displayText,
                Key = item.ID.ToString(),
                Description = item.ID.ToString() + " - " + displayText,
                IsResolved = true
            };
            entity.EntityData.Add(PickerData.LookupField, item[PickerData.LookupField]);
            for (int i = 0; i < PickerData.AdditionalSearchFields.Length; i++)
            {
                entity.EntityData[PickerData.AdditionalSearchFields[i]] = item[PickerData.AdditionalSearchFields[i]];
            }
            entity.EntityData["ID"] = entity.Key;
            return entity;
        }

        /// <summary>
        /// Finds listitems that match the search text.
        /// </summary>
        /// <param name="text">The search text</param>
        /// <returns></returns>
        protected SPListItemCollection SearchListItems(string text)
        {
            SPQuery query = new SPQuery().Where(GetCaml(text));
            if (!string.IsNullOrEmpty(PickerData.SearchScope))
            {
                query.ViewAttributes = string.Format("Scope=\"{0}\"", PickerData.SearchScope);
            }

            return List.GetItems(query);
        }

        /// <summary>
        /// Returns a CAML query to find listitems matching the search text.
        /// </summary>
        /// <param name="text">The search text</param>
        /// <returns></returns>
        protected IQueryBuilderExpression GetCaml(string text)
        {
            var camlExpression = QB.Or(QB.Contains(PickerData.LookupField, text));
            foreach (string field in PickerData.AdditionalSearchFields)
            {
                camlExpression.Add(QB.Contains(field, text));
            }
            var contentTypes = PickerData.GetContentTypes(List);
            if (contentTypes.Length > 0)
            {
                camlExpression = QB.And(camlExpression, QB.Or(contentTypes.Select(cT => QB.IsContentType(cT.Id)).ToArray()));
            }
            return camlExpression;
        }
    }
}
